﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Collections;
using System.Runtime.Serialization;
using System.IO;


namespace K.EnterpriseLibary
{
     ///<summary>
     ///静态工具类，处理基础类型数据
     ///</summary>
    public static class BasePublic
    {
        ///// <summary>
        ///// 判断是否为空，返回布尔型结果
        ///// </summary>
        ///// <param name="CheckObject"></param>
        ///// <returns></returns>
        //public static bool IsNull(this Object CheckObject)
        //{
        //    //DBNull 值不存在
        //    if (CheckObject == Convert.DBNull)
        //        return true;

        //    //null   引用类型变量的默认值，即只定义了变量，未实例化或赋值
        //    if ((object)CheckObject == null)
        //        return true;

        //    if (CheckObject is string)
        //    {
        //        return String.IsNullOrEmpty(((string)CheckObject)); //判断是否为空字符串
        //    }
        //    else if (CheckObject is ICollection) 
        //    {
        //        if (((ICollection)CheckObject).Count == 0) //判断集合中是否有记录
        //            return true;
        //    }
        //    else if (CheckObject is Array)
        //    {
        //        if (((Array)CheckObject).Length == 0)      //判断数组中是否有记录
        //            return true; 
        //    }

        //    return false;
        //}

        ///// <summary>
        ///// 检查是否为空，无返回值，系统直接处理
        ///// </summary>
        ///// <param name="CheckObject"></param>
        //public static void CheckNull(this Object CheckObject)
        //{
        //    CheckObject.CheckNull("The Object is Null!");
        //}

        ///// <summary>
        ///// 检查是否为空值，无返回值，用户自定义处理结果及扩展参数
        ///// </summary>
        ///// <param name="CheckObject">待检查的数据</param>
        ///// <param name="Message">自定义信息</param>
        ///// <param name="ExtendParameters">扩展参数</param>
        //public static void CheckNull(this Object CheckObject, string Message, params object[] ExtendParameters)
        //{
        //    if (CheckObject.IsNull())
        //        throw new Exception();  //此处待完善，需抛出自定义异常
        //}


    //}
        /// <summary>
        /// 判断对象是否为空
        /// </summary>
        /// <param name="testObject">测试对象</param>
        /// <returns>如果对象为DBNull或者为null则返回true,否则返回false</returns>
        public static bool IsNull(this Object testObject)
        {
            return testObject == Convert.DBNull || ((object)testObject) == null;
        }

        /// <summary>
        /// 对象是否为空
        /// </summary>
        /// <param name="testObject">测试对象</param>
        /// <returns>如果对象为DBNull或为null或者为空字符串或者为空数组，则返回true；否则返回false</returns>
        public static bool IsNullOrEmpty(this Object testObject)
        {
            if (testObject.IsNull())
                return true;

            if (testObject is string)
            {
                return String.IsNullOrEmpty(((string)testObject));
            }
            else if (testObject is ICollection)
            {
                if (((ICollection)testObject).Count == 0)
                    return true;
            }
            else if (testObject is Array)
            {
                if (((Array)testObject).Length == 0)
                    return true;
            }

            return false;
        }

        #region 檢查
        /// <summary>
        /// 檢查布爾型變量是否為True
        /// </summary>
        public static void CheckTrue(this bool boolValue, string message, params object[] extendParameters)
        {
            if (!boolValue)
                throw new KException(message, extendParameters);
        }

        /// <summary>
        /// 檢查布爾型變量是否為False
        /// </summary>
        public static void CheckFalse(this bool boolValue, string message, params object[] extendParameters)
        {
            CheckTrue(!boolValue, message, extendParameters);
        }

        /// <summary>
        /// 判断对象是否为空
        /// </summary>
        /// <param name="testObject">测试对象</param>
        /// <returns>如果对象为DBNull或者为null则返回true,否则返回false</returns>
        public static void CheckNullOrEmpty(this Object testObject)
        {
            testObject.CheckNullOrEmpty("Object is null or empty.");
        }

        /// <summary>
        /// 判断对象是否为空
        /// </summary>
        /// <param name="testObject">测试对象</param>
        /// <returns>如果对象为DBNull或者为null则返回true,否则返回false</returns>
        public static void CheckNullOrEmpty(this Object testObject, string message, params object[] extendParamters)
        {
            if (testObject.IsNullOrEmpty())
                throw new KException(message, extendParamters);

        }

        /// <summary>
        /// 判断对象是否为空
        /// </summary>
        /// <param name="testObject">测试对象</param>
        /// <returns>如果对象为DBNull或者为null则返回true,否则返回false</returns>
        public static void CheckNull(this Object testObject)
        {
            testObject.CheckNull("Object is null.");
        }

        /// <summary>
        /// 判断对象是否为空
        /// </summary>
        /// <param name="testObject">测试对象</param>
        /// <returns>如果对象为DBNull或者为null则返回true,否则返回false</returns>
        public static void CheckNull(this Object testObject, string message, params object[] extendParamters)
        {
            if (testObject.IsNull())
                throw new KException(message, extendParamters);
        }
        #endregion

        #region Object Clone
        public static object DataContractClone(this object srcObject)
        {
            if (srcObject == null)
                return null;

            Type dataType = srcObject.GetType();
            DataContractSerializer serializer = new DataContractSerializer(dataType);

            // Write
            System.IO.MemoryStream memoryStream = new MemoryStream();
            serializer.WriteObject(memoryStream, srcObject);

            // Read
            memoryStream.Seek(0, SeekOrigin.Begin);
            object returnObject = serializer.ReadObject(memoryStream);
            return returnObject;
        }

        /// <summary>
        /// 二進制克隆
        /// </summary>
        /// <param name="srcObject">需要克隆的對象</param>
        /// <returns>克隆后的對象</returns>
        public static object BinaryClone(this object srcObject)
        {
            return srcObject.BinaryClone(true);
        }
        /// <summary>
        /// 二進制克隆
        /// </summary>
        /// <param name="srcObject">需要克隆的對象</param>
        /// <param name="newID">是否產生新ID</param>
        /// <returns>克隆后的對象</returns>
        public static object BinaryClone(this object srcObject, bool newID)
        {
            if (srcObject == null)
                return null;

            System.IO.MemoryStream memoryStream = new MemoryStream();
            srcObject.WriteObjectToBinaryStream(memoryStream);

            memoryStream.Seek(0, SeekOrigin.Begin);
            object newObject = memoryStream.ReadObjectFromBinaryStream();
            // 產生NewID
            if (newID && !newObject.IsNull() && newObject is INewID)
            {
                newObject.Cast<INewID>().NewID();
            }
            return newObject;
        }
        #endregion

        /// <summary>
        /// 判断两个对象是否相等
        /// </summary>
        /// <param name="object1">对象1</param>
        /// <param name="object2">对象2</param>
        /// <returns>如果两个对象相等，则返回true；否则返回false</returns>
        public static bool IsEqual(this object object1, object object2)
        {
            if (object1 == Convert.DBNull && object2 == Convert.DBNull)
                return true;

            if (object1 == Convert.DBNull && object2 != Convert.DBNull)
                return false;

            if (object1 != Convert.DBNull && object2 == Convert.DBNull)
                return false;

            if (object1 == object2)
                return true;

            return object1.Equals(object2);
        }

        /// <summary>
        /// 判断两个对象是否相等
        /// </summary>
        /// <param name="object1">对象1</param>
        /// <param name="object2">对象2</param>
        /// <returns>如果两个对象相等，则返回true；否则返回false</returns>
        public static bool IsArrayEqual(this object[] array1, object[] array2)
        {
            if (array1 == array2)
                return true;

            if (array1 == null && array2 == null)
                return true;

            if (array1 == null && array2 != null)
                return false;

            if (array1 != null && array2 == null)
                return false;

            if (array1.Length != array2.Length)
                return false;

            for (int i = 0; i < array1.Length; i++)
            {
                if (!array1[i].IsEqual(array2[i]))
                    return false;
            }

            return true; ;
        }

        /// <summary>
        /// 數組連接
        /// </summary>
        public static object[] Concat(this object[] array1, params object[] array2)
        {
            if (array1.IsNull())
                return array2;

            if (array2.IsNull())
                return array1;
            IEnumerable<object> resultList = array1.Concat<object>(array2);
            return resultList.ToArray();
        }

        // 獲取子數組
        public static T[] SubArray<T>(this T[] sortedList, int startIndex)
        {
            if (sortedList.IsNull())
                return null;

            if (startIndex > sortedList.Length)
                return null;

            T[] array = new T[sortedList.Length - startIndex];
            sortedList.CopyTo(array, startIndex);
            return array;
        }

        /// <summary>
        /// 從鍵值對中獲取值
        /// </summary>
        /// <typeparam name="K">鍵類型</typeparam>
        /// <typeparam name="V">值類型</typeparam>
        /// <param name="keyValuePairs">鍵值對</param>
        /// <param name="key">鍵</param>
        /// <returns>值</returns>
        public static V GetValueByKey<K, V>(this KeyValuePair<K, V>[] keyValuePairs, K key)
        {
            keyValuePairs.CheckNullOrEmpty("Key value pair list is empty");

            KeyValuePair<K, V> keyValue = keyValuePairs.FirstOrDefault(p => p.Key.IsEqual(key));
            keyValue.CheckNull("Key does not exist in key value pair list"
                , "Key", key);

            return keyValue.Value;
        }
    }
}
